package online.struts.action;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import online.struts.mapping.RequestMapping;

import org.apache.logging.log4j.LogManager;

import common.db.ExclusiveException;

import core.exception.LogicalException;
import core.exception.PhysicalException;

/**
 * 基本アクション
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public abstract class BaseAction extends PerformAction {

	/** 更新完了後自画面 */
	public static final String ID_UPDATED = "UPDATED";
	/** 更新対象無し後新規入力 */
	public static final String ID_NG_REDIRECT = "NG_REDIRECT";
	/** システムエラー */
	public static final String ID_SYS_ERROR = "SYSTEM_ERROR";

	/**
	 * 処理振分け
	 *
	 * @param mapping RequestMappingオブジェクト
	 * @param uf 汎用フォーム
	 * @param request HttpServletRequestオブジェクト
	 * @param response HttpServletResponseオブジェクト
	 * @return 処理結果
	 */
	@Override
	public final String perform(final RequestMapping mapping, final UniForm uf,
					final HttpServletRequest request, final HttpServletResponse response) {
		try {
			// 実処理
			Method mt = RequestMapping.getActionMethod(this.getClass(),
							uf.getActionParameter().getAid(), UniForm.class);
			return String.class.cast(mt != null ? mt.invoke(this, uf) : ID_VIEW);
		} catch (final IllegalAccessException ex) {
			LogManager.getLogger().error(ex.getMessage(), ex);
			throw new PhysicalException(ex);
		} catch (final InvocationTargetException ex) {
			Throwable e = ex.getCause();
			if (LogicalException.class.isInstance(e)) {
				LogManager.getLogger().info(e.getMessage());
				return getReturn(LogicalException.class.cast(e));
			} else if (ExclusiveException.class.isInstance(e)) {
				throw ExclusiveException.class.cast(e);
			} else if (RuntimeException.class.isInstance(e)) {
				throw RuntimeException.class.cast(e);
			}
			throw new PhysicalException(e);
		}
	}

	/**
	 * 復帰値取得
	 * @param le 論理例外
	 * @return 復帰値
	 */
	private String getReturn(final LogicalException le) {
		String ret = le.getReturnCode();
		if (Objects.toString(ret, "").isEmpty()) {
			if (Objects.toString(le.getMessage(), "").isEmpty()) {
				ret = ID_SYS_ERROR;
			} else {
				ret = ID_NG;
			}
		}
		return ret;
	}
}
